/**
 * 项目名：	Rumba Plan
 * 
 * 版权所有(C)，上海海鼎信息工程股份有限公司，2006，所有权利保留。
 * 
 * 文件名：	BDomainMgr.java
 * 模块说明：	
 * 修改历史：
 * 2006-6-22 - lxm - 创建。
 */
package com.hd123.rumba.domain.biz;

import java.util.ArrayList;
import java.util.List;

import net.sf.hibernate.HibernateException;
import net.sf.hibernate.Transaction;

import com.hd123.rumba.cartridge.CCartFunctionView;
import com.hd123.rumba.cartridge.ICartFunctionView;
import com.hd123.rumba.cartridge.ICartridgeMgr;
import com.hd123.rumba.cartridge.biz.BCartFunctionView;
import com.hd123.rumba.cartridge.biz.IBCartridgeMgr;
import com.hd123.rumba.cartridge.biz.SCartFunctionView;
import com.hd123.rumba.domain.CDomain;
import com.hd123.rumba.domain.IDomain;
import com.hd123.rumba.domain.IDomainMgr;
import com.hd123.rumba.exception.BusinessException;
import com.hd123.rumba.gwt.base.client.biz.BPersistent;
import com.hd123.rumba.log.RumbaLogger;
import com.hd123.rumba.organization.biz.BOrganization;
import com.hd123.rumba.organization.biz.IBOrganizationMgr;
import com.hd123.rumba.runtime.IManager;
import com.hd123.rumba.runtime.NamingMgr;
import com.hd123.rumba.runtime.OperateContext;
import com.hd123.rumba.runtime.backprocess.BackProcess;
import com.hd123.rumba.runtime.backprocess.Progress;
import com.hd123.rumba.runtime.biz.BManager;
import com.hd123.rumba.util.ClassifiedHashtable;

/**
 * 域 | 业务层 | 管理员 | 实现类
 * 
 * @author lxm
 * 
 */
public class BDomainMgr extends BManager implements IBDomainMgr {

  public IManager getPerzMgr() throws BusinessException {
    return getDomainMgr();
  }

  public BDomain loadDomain(String uuid) throws BusinessException, HibernateException {
    checkParameterNotNull(uuid, "uuid");

    BDomain bdomain = null;
    IDomain domain = getDomainMgr().getDomain(uuid);
    if (domain != null) {
      bdomain = new BDomain();
      bdomain.readFrom(domain);

      List<ICartFunctionView> pcfvs = getDomainMgr().getCFVsByDomain(domain);
      List<SCartFunctionView> cfvs = new ArrayList();
      for (int i = 0; i < cfvs.size(); i++) {
        SCartFunctionView cfv = new SCartFunctionView();
        cfv.readFrom(pcfvs.get(i));
        cfvs.add(cfv);
      }
      bdomain.setFuncViews(cfvs);
    }
    return bdomain;
  }

  public SDomain getDomain(String uuid) throws BusinessException, HibernateException {
    checkParameterNotNull(uuid, "uuid");

    IDomain pdomain = getDomainMgr().getDomain(uuid);
    if (pdomain == null)
      return null;
    else {
      SDomain domain = new SDomain();
      domain.readFrom(pdomain);
      return domain;
    }
  }

  public SDomain getRootDomain() throws BusinessException, HibernateException {
    IDomain pdomain = getDomainMgr().getRootDomain();
    if (pdomain == null)
      return null;
    else {
      SDomain domain = new SDomain();
      domain.readFrom(pdomain);
      return domain;
    }
  }

  public int getRelativePosition(IDomain currentDomain, BDomain domain) throws BusinessException,
      HibernateException {
    checkParameterNotNull(currentDomain, "currentDomain");
    checkParameterNotNull(domain, "domain");
    if (currentDomain.getUuid().equals(domain.getUuid()))
      return VALUE_RELATIONSHIP_SELF;

    IBOrganizationMgr borgMgr = (IBOrganizationMgr) NamingMgr.getInstance().lookupMgr(
        IBOrganizationMgr.class);
    BOrganization currOrg = (BOrganization) borgMgr.getOrganizationByOrgDomain(currentDomain
        .getUuid(), BOrganization.class);
    if (currOrg == null)
      return VALUE_RELATIONSHIP_LOWER;

    BOrganization org = (BOrganization) borgMgr.getOrganizationByOrgDomain(domain.getUuid(),
        BOrganization.class);
    if (org == null)
      return VALUE_RELATIONSHIP_UPPER;

    return borgMgr.getRelativePosition(currOrg, org);
  }

  public List<SCartFunctionView> getCFVsByDomain(String domainUuid) throws BusinessException,
      HibernateException {
    checkParameterNotNull(domainUuid, "domainUuid");

    IDomain domain = getDomainMgr().getDomain(domainUuid);
    if (domain == null)
      throw new BusinessException("找不到指定的" + CDomain.CAPTION_CLASS + "(" + CDomain.CAPTION_UUID
          + "=" + domainUuid + ")。");
    List<SCartFunctionView> cfvs = new ArrayList();
    List<ICartFunctionView> pcfvs = getDomainMgr().getCFVsByDomain(domain);
    for (int i = 0; i < pcfvs.size(); i++) {
      SCartFunctionView cfv = new SCartFunctionView();
      cfv.readFrom(pcfvs.get(i));
      cfvs.add(cfv);
    }
    return cfvs;
  }

  /** @see IBDomainMgr#analyseLoadingCFVs(String, String) */
  public List<BCartFunctionView> analyseLoadingCFVs(String targetCFVUuid, String domainUuid)
      throws BusinessException, HibernateException {
    List<BCartFunctionView> bcfvs = new ArrayList();
    List<SCartFunctionView> domainCFVs = getCFVsByDomain(domainUuid);
    BCartFunctionView targetCFV = getBCartMgr().getFunctionView(targetCFVUuid);
    doAnalyseLoadingCFV(bcfvs, targetCFV, domainCFVs);
    return bcfvs;
  }

  /**
   * @see IBDomainMgr#loadCFVsToDomainT(String, String, OperateContext, long)
   */
  public void loadCFVsToDomainT(String targetCFVUuid, String domainUuid, OperateContext operate,
      long oca) throws BusinessException, HibernateException, InterruptedException {
    RumbaLogger logger = RumbaLogger.getLogger(this.getClass());
    logger.setOperator(operate.getOperator());
    logger.info("预处理");
    Progress progress = BackProcess.getProgress();

    logger.debug("analyseLoadingCFVs ...");
    List<BCartFunctionView> bcfvs = this.analyseLoadingCFVs(targetCFVUuid, domainUuid);
    IDomain domain = getDomainMgr().getDomain(domainUuid);
    ClassifiedHashtable h = this.checkOca(domain, oca, CDomain.CAPTION_CLASS, domain.getNameCode());
    if (h != null)
      throw new BusinessException(h.getAllMessages());

    progress.setMinValue(0);
    progress.setMaxValue(bcfvs.size() * 5);
    for (int i = 0; i < bcfvs.size(); i++) {
      BCartFunctionView bcfv = bcfvs.get(i);
      String msg = "开始装载" + CCartFunctionView.CAPTION_CLASS + ": " + bcfv.getGlobalCaption() + "("
          + bcfv.getUuid() + ")";
      logger.info(msg);
      progress.putMessage(msg);

      // 执行功能视图的装载处理。
      Progress subPgr = BackProcess.getProgressStack2().pushNew(4);
      subPgr.setCaption("执行装载 " + bcfv.getGlobalCaption() + " 之前的处理");
      bcfv.onLoadToDomain(domain, operate.getOperator());
      BackProcess.getProgressStack2().pop();

      assignCFVToDomainT(bcfv.getUuid(), domain, operate);
      // Thread.sleep(800);
      progress.stepBy(1);
    }
  }

  /** @see IBDomainMgr#analyseUnloadingCFVs(String, String) */
  public List<BCartFunctionView> analyseUnloadingCFVs(String targetCFVUuid, String domainUuid)
      throws BusinessException, HibernateException {
    List<BCartFunctionView> bcfvs = new ArrayList();
    List<SCartFunctionView> domainCFVs = getCFVsByDomain(domainUuid);
    BCartFunctionView targetCFV = getBCartMgr().getFunctionView(targetCFVUuid);
    doAnalyseUnloadingCFV(bcfvs, targetCFV, domainCFVs);
    return bcfvs;
  }

  /**
   * @see IBDomainMgr#unloadCFVsFromDomainT(String, String, OperateContext,
   *      long, Progress)
   */
  public void unloadCFVsFromDomainT(String targetCFVUuid, String domainUuid,
      OperateContext operate, long oca) throws BusinessException, HibernateException,
      InterruptedException {
    RumbaLogger logger = RumbaLogger.getLogger(this.getClass());
    logger.setOperator(operate.getOperator());
    logger.info("预处理");
    Progress progress = BackProcess.getProgress();

    logger.debug("analyseUnloadingCFVs ...");
    List<BCartFunctionView> bcfvs = this.analyseUnloadingCFVs(targetCFVUuid, domainUuid);
    IDomain domain = getDomainMgr().getDomain(domainUuid);
    ClassifiedHashtable h = this.checkOca(domain, oca, CDomain.CAPTION_CLASS, domain.getNameCode());
    if (h != null)
      throw new BusinessException(h.getAllMessages());

    progress.setMinValue(0);
    progress.setMaxValue(bcfvs.size() * 5);
    for (int i = 0; i < bcfvs.size(); i++) {
      BCartFunctionView bcfv = bcfvs.get(i);
      String msg = "开始卸载" + CCartFunctionView.CAPTION_CLASS + " " + bcfv.getGlobalCaption() + "("
          + bcfv.getUuid() + ")";
      logger.info(msg);
      progress.putMessage(msg);

      // 执行功能视图的卸载处理。
      Progress subPrg = BackProcess.getProgressStack2().pushNew(4);
      subPrg.setCaption("执行卸载 " + bcfv.getGlobalCaption() + " 之前的处理");
      bcfv.onUnloadFromDomain(domain, operate.getOperator());
      BackProcess.getProgressStack2().pop();

      removeCFVFromDomainT(bcfv.getUuid(), domain, operate);
      progress.stepBy(1);
    }
  }

  public <T extends BPersistent> T getDomainByCode(String code, Class<T> bizClass)
      throws BusinessException, HibernateException {
    this.checkParameterNotNull(bizClass, "bizClass");
    IDomain perz = this.getDomainMgr().getDomainByCode(code);
    if (perz == null)
      return null;
    T biz = this.createBizClass2(bizClass);
    this.assignPerzToBiz(perz, biz);
    return biz;
  }

  private IDomainMgr domainMgr = null;
  private IBCartridgeMgr bcartMgr = null;
  private ICartridgeMgr cartMgr = null;

  private IDomainMgr getDomainMgr() throws BusinessException {
    if (domainMgr == null)
      domainMgr = (IDomainMgr) NamingMgr.getInstance().lookupMgr(IDomainMgr.class);
    return domainMgr;
  }

  private IBCartridgeMgr getBCartMgr() throws BusinessException {
    if (bcartMgr == null)
      bcartMgr = (IBCartridgeMgr) NamingMgr.getInstance().lookupMgr(IBCartridgeMgr.class);
    return bcartMgr;
  }

  private ICartridgeMgr getCartMgr() throws BusinessException {
    if (cartMgr == null)
      cartMgr = (ICartridgeMgr) NamingMgr.getInstance().lookupMgr(ICartridgeMgr.class);
    return cartMgr;
  }

  private void doAnalyseLoadingCFV(List<BCartFunctionView> bcfvs, BCartFunctionView bcfv,
      List<SCartFunctionView> domainCFVs) throws BusinessException {
    boolean has = false;
    for (int i = 0; i < domainCFVs.size(); i++)
      if (domainCFVs.get(i).getUuid().equals(bcfv.getUuid())) {
        has = true;
        break;
      }
    if (has)
      return;

    bcfvs.add(0, bcfv);

    for (int i = 0; i < bcfv.getReferences().size(); i++) {
      String refCFVPrefix = bcfv.getReferences().get(i).getRefCFVPrefix();
      BCartFunctionView refCFV = getBCartMgr().getFunctionViewByPrefix(refCFVPrefix);
      doAnalyseLoadingCFV(bcfvs, refCFV, domainCFVs);
    }
  }

  private void doAnalyseUnloadingCFV(List<BCartFunctionView> bcfvs, BCartFunctionView bcfv,
      List<SCartFunctionView> domainCFVs) throws BusinessException {
    boolean done = false;
    for (int i = 0; i < domainCFVs.size(); i++) {
      SCartFunctionView scfv = domainCFVs.get(i);

      // 跳过已经加入到结果卸载列表bcfvs的。
      boolean exists = false;
      for (int j = 0; j < bcfvs.size(); j++)
        if (scfv.getUuid().equals(bcfvs.get(j).getUuid())) {
          exists = true;
          break;
        }
      if (exists)
        continue;

      // 确保只有domainCFVs中存在指定卸载的bcfv
      if (scfv.getUuid().equals(bcfv.getUuid())) {
        done = true;
        continue;
      }

      // 检查是否依赖当前bcfv，若依赖则加入结果卸载列表bcfvs（递归调用）
      BCartFunctionView bcfv2 = getBCartMgr().getFunctionView(scfv.getUuid());
      for (int j = 0; j < bcfv2.getReferences().size(); j++) {
        String refCFVPrefix = bcfv2.getReferences().get(j).getRefCFVPrefix();
        if (refCFVPrefix.equals(bcfv.getPrefix())) {
          doAnalyseUnloadingCFV(bcfvs, bcfv2, domainCFVs);
          break;
        }
      }
    }

    if (done)
      bcfvs.add(bcfv);
  }

  private void assignCFVToDomainT(String cfvUuid, IDomain domain, OperateContext operate)
      throws BusinessException, HibernateException {
    ICartFunctionView pcfv = getCartMgr().getFunctionView(cfvUuid);
    Transaction tx = getSession().beginTransaction();
    try {
      getDomainMgr().assignCFVToDomain(pcfv, domain, operate);
      tx.commit();
    } catch (Exception e) {
      tx.rollback();
      throw new BusinessException(e);
    } finally {
      getSession().flush();
    }
  }

  private void removeCFVFromDomainT(String cfvUuid, IDomain domain, OperateContext operate)
      throws BusinessException, HibernateException {
    ICartFunctionView pcfv = getCartMgr().getFunctionView(cfvUuid);
    Transaction tx = getSession().beginTransaction();
    try {
      getDomainMgr().removeCFVToDomain(pcfv, domain, operate);
      tx.commit();
    } catch (Exception e) {
      tx.rollback();
      throw new BusinessException(e);
    } finally {
      getSession().flush();
    }
  }

  public List<SDomain> loadDomainsByParent(String domainUuid) throws BusinessException,
      HibernateException {
    checkParameterNotNull(domainUuid, "domainUuid");
    IDomain domain = getDomainMgr().getDomain(domainUuid);
    List<IDomain> list = getDomainMgr().getDomainsByParent(domain);
    List<SDomain> domains = new ArrayList<SDomain>();
    for (int i = 0; i < list.size(); i++) {
      SDomain d = new SDomain();
      d.readFrom(list.get(i));
      domains.add(d);
    }
    return domains;
  }
}
